/**
*	Carte
*	v 1.11
*/


#ifndef _CARTE_H_
#define _CARTE_H_

// include du jeu
#include "defines.h"
#include "Element.h"
#include "Batiment.h"
#include "Entite.h"
#include "Position.h"
#include "Deplacement.h"
#include "noeud.h"

// include librairies c++
#include <iostream>
#include <vector>
#include <deque>

class Carte{

	public :
		// Pour les elements on verra plus tard : TODO

		/**
		 * @brief Constructeur de carte, initialise ses variables
		 *
		 * @param b Un pointeur vers la liste des batiments du monde
		 * @param en Un pointeur vers la liste des entites du monde
		 * @todo Prendre en compte les éléments & autre ... ?
		 */
		Carte(std::vector<Batiment*> *b,std::vector<Entite*> *en,/* std::vector<Element> el,*/ Taille t);

		/**
		 * @brief Teste si deux blocs peuvent se rentrer dedans en X (partage de même coordonnées)
		 *
		 * @param a Un bloc à tester
		 * @param b L'autre bloc à tester
		 * @todo Passer en public static
		 */
		static bool estAligneX(Bloc a, Bloc b);

		/**
		 * @brief Teste si deux blocs peuvent se rentrer dedans en Y (partage de même coordonnées)
		 *
		 * @param a Un bloc à tester
		 * @param b L'autre bloc à tester
		 * @todo Passer en public static
		 */
		static bool estAligneY(Bloc a, Bloc b);

		/**
		 * @brief Teste si deux blocs sont en collision
		 *
		 * @param a Un bloc à tester
		 * @param b L'autre bloc à tester
		 */
		static bool collision(Bloc a, Bloc b);

		/**
		 * @brief Teste si un bloc est proche d'une position
		 *
		 * @param a Un bloc à tester
		 * @param p La position dont on veut savoir si il est proche
		 * @note La fonction doit etre mieux testée
		 * @todo Tester la fonction
		 */
		static bool estProche(Bloc a, Position p);


		/**
		*	Retourne la distance entre deux points
		*
		*/
		static float distance(Position a, Position b);

		/**
		 * @brief Retourne le point d'intersection de deux droites déterminées
		 * par les couples (a1,a2) et (b1,b2)
		 *
		 * @param a1 L'origine de la premiere droite
		 * @param a2 La destination de la premiere droite
		 * @param b1 L'origine de la deuxieme droite
		 * @param b2 La destination de la deuxieme droite
		 * @return Le point d'intersection entre les deux droites 
		 * @todo Tester la fonction
		 */
		static Position intersection(Position a1, Position a2, Position b1, Position b2);	

		/**
		 * @brief Retourne le point d'intersection de d'une droite et d'un bloc
		 *
		 * @param a1 L'origine de la premiere droite
		 * @param a2 La destination de la premiere droite
		 * @param b Le bloc à detecter
		 * @return Le point d'intersection le plus proche de la source
		 * @todo Tester la fonction
		 */
		static Position intersection(Position a1, Position a2, Bloc b);		

		/**
		 * @brief Retourne si oui ou non le point p est contenu dans le bloc b
		 *
		 * @param p La position a tester
		 * @param b Le bloc dont on veut verifier la présence du point
         * @param bordsInclus si on considere une position sur un segment comme étant dans le bloc
		 * @return Vrai ou Faux
		 * @todo Tester la fonction
		 */
		static bool estPositionDansBloc( Position p, Bloc b, bool bordsInclus);

		/**
		 * @brief Retourne si oui ou non le point p est sur le segment (src,dest)
		 *
		 * @param p La position a tester
		 * @param src Le point de départ du segment
		 * @param dest Le point d'arrivée du segment
		 * @return Vrai ou Faux
		 * @todo Tester la fonction
		 */
		static bool estPositionDansSegment( Position src, Position dest, Position p);


		/**
		 * @brief Teste si l'emplacement demandé est vide, selon que l'entite existe ou pas encore
		 *
		 * Cette fonction nous dit si il est possible d'utiliser tel emplacement. Selon que l'element 
		 * voulu, c'est à dire si il existe déjà il pourra rentrer en collision avec lui meme lors d'un 
		 * deplacement. Si il n'existe alors il ne faudra aucune collision.
		 *
		 * @param b Le bloc dont on doit verifier la possibilite d'emplacement
		 * @param existe Si on a affaire à une unité déjà existante ou non
		 * 
		 */
		bool estEmplacementPossible( Bloc b, int existe);

		/**
		 * @brief Calcule le coefficient a de la droite y = ax + b
		 *
		 * @param src L'origine de la position
		 * @param dest La destination de la droite
		 * @return Le coefficient directeur de la droite passant par les deux positions
		 * @todo Passer en public static
		 */
		static float getCoefficient( Position src, Position dest);



		/**
		 * @brief Permet de connaitre la taille de la carte
		 */
		Taille getTaille();

		/**
		 * @brief Retourne le premier obstacle entre les deux positions, prend en paramametre
		 * une entite si c'est elle qui lance la fonction (obligatoirement en obstacle avec elle meme 
		 * dans ce cas)
		 */
		Bloc premierObstacle( Position src, Position dest, Entite *e );

		/**
		 * @brief Retourne le premier obstacle entre les deux positions, prend en paramametre
		 * une entite si c'est elle qui lance la fonction (obligatoirement en obstacle avec elle meme 
		 * dans ce cas) et retourne le point d'impact
		 */
		Bloc premierObstacle( Position src, Position dest, Entite *e , Position* impact);

		/**
		* @brief Retourne les coins proches de la position demandée quand cette derniere appartient à
		* un Bloc qui est passé en paramètre
		*/
		std::vector<Position> coinsDeBlocSurSegment( Bloc b, Position p);


	private :
		//******************
		//   Relatifs au monde	

		/// La liste des batiments du monde
		std::vector<Batiment*> *batiments; 
	
		/// La liste des entites du monde
		std::vector<Entite*> *entites; 

		/// La liste des elements du monde
		//std::vector<Element> elements; 

		/// Le pas utilisé pour les calculs de deplacements (voir #define MAX_PAS )
		float pas; 

		/// La taille de la carte
		Taille taille; 
};

#endif
